import type { Menu, MenuModule } from '@/router/types';

import type { RouteRecordNormalized } from 'vue-router';

import { isHttpUrl } from '@eacloud/utils';

import { AuthModeEnum } from '@/enums/appEnum';
import { router } from '@/router';
import { getAllParentPath } from '@/router/helper/menu';
import { useAppStoreWithOut } from '@/store/modules/app';
import { useAuthStore } from '@/store/modules/auth';
import { filter } from '@/utils/helper/tree';
import { pathToRegexp } from 'path-to-regexp';

const modules = import.meta.glob('../routes/modules/**/*.ts', { eager: true });

export const menuModules: MenuModule[] = [];

Object.keys(modules).forEach((key) => {
  const mod = (modules as Recordable)[key].default || {};
  const modList = Array.isArray(mod) ? [...mod] : [mod];
  menuModules.push(...modList);
});

// ===========================
// ==========Helper===========
// ===========================

const getAuthMode = () => {
  const appStore = useAppStoreWithOut();
  return appStore.getProjectConfig.authMode;
};
const isBackMode = () => {
  return getAuthMode() === AuthModeEnum.BACK;
};

const isRouteMappingMode = () => {
  return getAuthMode() === AuthModeEnum.ROUTE_MAPPING;
};

const isRoleMode = () => {
  return getAuthMode() === AuthModeEnum.ROLE;
};

async function getAsyncMenus() {
  const authStore = useAuthStore();
  // 递归过滤所有隐藏的菜单
  const menuFilter = (items: Menu[]) => {
    return items.filter((item) => {
      const show = !item.meta?.hideMenu && !item.hideMenu;
      if (show && item.children) {
        item.children = menuFilter(item.children);
      }
      return show;
    });
  };
  if (isBackMode()) {
    return menuFilter(authStore.getBackMenuList);
  }
  if (isRouteMappingMode()) {
    return menuFilter(authStore.getFrontMenuList);
  }
  return authStore.getStaticMenuList;
}

export const getMenus = async (): Promise<Menu[]> => {
  const menus = await getAsyncMenus();
  if (isRoleMode()) {
    const routes = router.getRoutes();
    return filter(menus, basicFilter(routes));
  }
  return menus;
};

export async function getCurrentParentPath(currentPath: string) {
  const menus = await getAsyncMenus();
  const allParentPath = await getAllParentPath(menus, currentPath);
  return allParentPath?.[0];
}

// Get the level 1 menu, delete children
export async function getShallowMenus(): Promise<Menu[]> {
  const menus = await getAsyncMenus();
  const shallowMenuList = menus.map((item) => ({ ...item, children: undefined }));
  if (isRoleMode()) {
    const routes = router.getRoutes();
    return shallowMenuList.filter(basicFilter(routes));
  }
  return shallowMenuList;
}

// Get the children of the menu
export async function getChildrenMenus(parentPath: string) {
  const menus = await getMenus();
  const parent = menus.find((item) => item.path === parentPath);
  if (!parent || !parent.children || !!parent?.meta?.hideChildrenInMenu) {
    return [] as Menu[];
  }
  if (isRoleMode()) {
    const routes = router.getRoutes();
    return filter(parent.children, basicFilter(routes));
  }
  return parent.children;
}

function basicFilter(routes: RouteRecordNormalized[]) {
  return (menu: Menu) => {
    const matchRoute = routes.find((route) => {
      if (isHttpUrl(menu.path)) return true;

      if (route.meta?.carryParam) {
        return pathToRegexp(route.path).test(menu.path);
      }
      const isSame = route.path === menu.path;
      if (!isSame) return false;

      if (route.meta?.ignoreAuth) return true;

      return isSame || pathToRegexp(route.path).test(menu.path);
    });

    if (!matchRoute) return false;
    menu.icon = (menu.icon || matchRoute.meta.icon) as string;
    menu.meta = matchRoute.meta;
    return true;
  };
}
